<template>
  <div class="filter-group-config" :class="{ 'nested-group': showDelete }">
    <Card
      :title="title"
      :bordered="false"
      class="mb-4"
      :class="{ 'nested-card': showDelete }"
    >
      <template #extra>
        <Space v-if="hasAccessByCodes(['RoleResource:SetFilterGroups'])">
          <Button type="primary" size="small" @click="addRule">
            <template #icon><PlusOutlined /></template>
            添加规则
          </Button>
          <Button type="primary" size="small" @click="addGroup">
            <template #icon><PlusOutlined /></template>
            添加分组
          </Button>
          <Button
            v-if="showDelete"
            danger
            size="small"
            @click="$emit('delete')"
          >
            <template #icon><DeleteOutlined /></template>
            删除分组
          </Button>
        </Space>
      </template>

      <!-- 操作符选择 -->
      <div class="mb-4">
        <RadioGroup v-model:value="innerValue.operate" button-style="solid">
          <RadioButton :value="FilterOperate.And">并且(AND)</RadioButton>
          <RadioButton :value="FilterOperate.Or">或者(OR)</RadioButton>
        </RadioGroup>
      </div>

      <!-- 过滤规则列表 -->
      <div v-if="innerValue.rules.length > 0" class="mb-4">
        <List bordered>
          <ListItem
            v-for="(rule, index) in innerValue.rules"
            :key="index"
            class="rule-item"
          >
            <div class="flex w-full items-center">
              <FormItem class="mb-0 mr-2 flex-1">
                <Select
                  v-model:value="rule.field"
                  placeholder="字段名称"
                  style="width: 100%"
                  :getPopupContainer="(triggerNode) => triggerNode.parentNode"
                >
                  <SelectOption
                    v-for="option in fieldOptions"
                    :key="option.value"
                    :value="option.value"
                  >
                    {{ option.label }}
                  </SelectOption>
                </Select>
              </FormItem>
              <FormItem class="mb-0 mr-2 flex-1">
                <Select
                  v-model:value="rule.operate as FilterOperate"
                  style="width: 100%"
                  :getPopupContainer="(triggerNode) => triggerNode.parentNode"
                >
                  <SelectOption
                    v-for="operator in getAvailableOperators(rule.field)"
                    :key="operator"
                    :value="operator"
                  >
                    {{ getOperatorLabel(operator) }}
                  </SelectOption>
                </Select>
              </FormItem>
              <FormItem class="mb-0 mr-2 flex-1">
                <FormItem class="mb-0 mr-2 flex-1">
                  <template
                    v-if="getFieldType(rule.field) === 'System.Boolean'"
                  >
                    <Switch
                      :checked="rule.value === 'true'"
                      checked-children="是"
                      un-checked-children="否"
                      @update:checked="
                        (checked) => (rule.value = String(checked))
                      "
                    />
                  </template>
                  <template
                    v-else-if="getFieldType(rule.field) === 'System.DateTime'"
                  >
                    <DatePicker
                      :value="rule.value || undefined"
                      style="width: 100%"
                      show-time
                      format="YYYY-MM-DD HH:mm:ss"
                      value-format="YYYY-MM-DD HH:mm:ss"
                      placeholder="请选择日期时间"
                      @change="(_: any, val: string) => (rule.value = val)"
                    />
                  </template>
                  <template v-else-if="isNumberType(rule.field)">
                    <InputNumber
                      :value="rule.value ? Number(rule.value) : undefined"
                      style="width: 100%"
                      placeholder="请输入数字"
                      :min="-999999999"
                      :max="999999999"
                      :precision="0"
                      @change="(val) => (rule.value = val?.toString() || null)"
                    />
                  </template>
                  <template v-else>
                    <Input
                      :value="rule.value || ''"
                      placeholder="请输入值"
                      allow-clear
                      @change="
                        (e: Event) =>
                          (rule.value =
                            (e.target as HTMLInputElement).value || null)
                      "
                    />
                  </template>
                </FormItem>
              </FormItem>
              <Button danger size="small" @click="removeRule(index)">
                <template #icon><DeleteOutlined /></template>
              </Button>
            </div>
          </ListItem>
        </List>
      </div>

      <!-- 嵌套的过滤分组 -->
      <div
        v-if="innerValue.groups && innerValue.groups.length > 0"
        class="nested-groups-container"
      >
        <template v-for="(group, index) in innerValue.groups" :key="index">
          <div class="nested-group-wrapper">
            <div class="group-connector"></div>
            <filter-group-config
              v-if="group"
              v-model:modelValue="innerValue.groups[index]"
              :title="`子分组 ${index + 1}`"
              :show-delete="true"
              @delete="removeGroup(index)"
            />
          </div>
        </template>
      </div>
    </Card>
  </div>
</template>

<script lang="ts" setup>
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue';
import { computed, watch } from 'vue';
import type { FilterGroup, FilterRule } from '#/utils/daprplus/types';
import { FilterOperate } from '#/utils/daprplus/types';
import { useAccess } from '@vben/access';
import type {
  EntityMetadata,
  EntityProperty,
} from '#/api/daprplus/auth/resource';
import {
  Card,
  Space,
  Button,
  RadioGroup,
  RadioButton,
  List,
  ListItem,
  FormItem,
  Input,
  InputNumber,
  DatePicker,
  Checkbox,
  Select,
  SelectOption,
  Switch,
} from 'ant-design-vue';

// 接口定义
interface Props {
  modelValue?: FilterGroup;
  title?: string;
  showDelete?: boolean;
  entityMetadata?: EntityMetadata;
}

const { hasAccessByCodes } = useAccess();

const props = withDefaults(defineProps<Props>(), {
  title: '过滤条件',
  showDelete: false,
});

const emit = defineEmits(['update:modelValue', 'delete']);

// 默认值
const defaultFilterGroup: FilterGroup = {
  groups: [],
  operate: FilterOperate.And,
  rules: [],
};

// =============== 计算属性 ===============

// 过滤组的计算属性
const innerValue = computed({
  get: () => props.modelValue || defaultFilterGroup,
  set: (value) => emit('update:modelValue', value),
});

// 字段选项的计算属性
const fieldOptions = computed(() => {
  if (!props.entityMetadata?.properties) return [];

  return props.entityMetadata.properties.map((prop: EntityProperty) => ({
    value: prop.name,
    label: prop.display || prop.name,
  }));
});

// =============== 字段类型处理 ===============

// 获取字段属性
const getFieldProperty = (fieldName: string): EntityProperty | null => {
  if (!props.entityMetadata?.properties) return null;
  return (
    props.entityMetadata.properties.find((prop) => prop.name === fieldName) ||
    null
  );
};

// 获取字段类型
const getFieldType = (fieldName: string) => {
  const field = getFieldProperty(fieldName);
  if (!field?.typeName) return null;

  // 处理可空类型
  if (field.typeName.startsWith('System.Nullable`1[[')) {
    const match = field.typeName.match(/System\.Nullable`1\[\[(.*?),/);
    return match ? match[1] : null;
  }

  return field.typeName;
};

// 判断是否为数值类型
const isNumberType = (fieldName: string) => {
  const type = getFieldType(fieldName);
  return [
    'System.Int32',
    'System.Int64',
    'System.Decimal',
    'System.Double',
  ].includes(type || '');
};

// =============== 操作符处理 ===============

// 获取可用的操作符
const getAvailableOperators = (fieldName: string) => {
  const fieldType = getFieldType(fieldName);
  if (!fieldType) return [];

  const baseOperators = [FilterOperate.Equal, FilterOperate.NotEqual];

  switch (fieldType) {
    case 'System.String':
      return [
        ...baseOperators,
        FilterOperate.Contains,
        FilterOperate.NotContains,
        FilterOperate.StartsWith,
        FilterOperate.EndsWith,
      ];
    case 'System.Int64':
    case 'System.Int32':
    case 'System.Decimal':
    case 'System.Double':
    case 'System.DateTime':
      return [
        ...baseOperators,
        FilterOperate.Less,
        FilterOperate.LessOrEqual,
        FilterOperate.Greater,
        FilterOperate.GreaterOrEqual,
      ];
    case 'System.Boolean':
      return baseOperators;
    default:
      return baseOperators;
  }
};

// 获取操作符的显示文本
const getOperatorLabel = (operator: FilterOperate) => {
  const operatorLabels = {
    [FilterOperate.And]: '并且',
    [FilterOperate.Or]: '或者',
    [FilterOperate.Equal]: '等于',
    [FilterOperate.NotEqual]: '不等于',
    [FilterOperate.Less]: '小于',
    [FilterOperate.LessOrEqual]: '小于等于',
    [FilterOperate.Greater]: '大于',
    [FilterOperate.GreaterOrEqual]: '大于等于',
    [FilterOperate.Contains]: '包含',
    [FilterOperate.NotContains]: '不包含',
    [FilterOperate.StartsWith]: '以...开头',
    [FilterOperate.EndsWith]: '以...结尾',
  };
  return operatorLabels[operator as keyof typeof operatorLabels] || operator;
};

// =============== 规则和分组操作 ===============

// 添加新规则
const addRule = () => {
  const newRule: FilterRule = {
    field: '',
    operate: FilterOperate.Equal,
    value: '',
    isLowerCaseToUpperCase: true,
  };

  emit('update:modelValue', {
    ...innerValue.value,
    rules: [...innerValue.value.rules, newRule],
  });
};

// 移除规则
const removeRule = (index: number) => {
  const updatedRules = [...innerValue.value.rules];
  updatedRules.splice(index, 1);

  emit('update:modelValue', {
    ...innerValue.value,
    rules: updatedRules,
  });
};

// 添加新分组
const addGroup = () => {
  const newGroup: FilterGroup = {
    groups: [],
    operate: FilterOperate.And,
    rules: [],
  };

  emit('update:modelValue', {
    ...innerValue.value,
    groups: [...(innerValue.value.groups || []), newGroup],
  });
};

// 移除分组
const removeGroup = (index: number) => {
  if (!innerValue.value.groups) return;

  const updatedGroups = [...innerValue.value.groups];
  updatedGroups.splice(index, 1);

  emit('update:modelValue', {
    ...innerValue.value,
    groups: updatedGroups,
  });
};

// =============== 监听器 ===============

// 监听规则变化，处理类型转换
watch(
  () => innerValue.value.rules,
  (rules) => {
    if (!rules) return;

    rules.forEach((rule) => {
      // 处理操作符类型
      if (rule.operate && typeof rule.operate === 'string') {
        rule.operate = rule.operate as unknown as FilterOperate;
      }

      // 确保值不为null
      if (rule.value === null) {
        rule.value = '';
      }
    });
  },
  { deep: true },
);
</script>

<style scoped>
.filter-group-config {
  width: 100%;
}

.nested-group {
  margin-left: 20px;
  position: relative;
}

.nested-card {
  border-left: 2px solid #1890ff !important;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.09);
  background-color: rgba(240, 242, 245, 0.5);
}

.rule-item {
  transition: all 0.3s;
}

.rule-item:hover {
  background-color: rgba(24, 144, 255, 0.05);
}

.nested-groups-container {
  margin-top: 16px;
}

.nested-group-wrapper {
  position: relative;
  padding-top: 8px;
  margin-bottom: 8px;
}

.group-connector {
  position: absolute;
  left: -20px;
  top: 0;
  height: 100%;
  width: 20px;
  border-left: 2px solid #d9d9d9;
  border-bottom: 2px solid #d9d9d9;
  border-bottom-left-radius: 8px;
}

.nested-group-wrapper:last-child .group-connector {
  height: 20px;
}
</style>
